package org.example.xtcs.anpes1;

import cn.hutool.core.util.StrUtil;
import com.google.auto.service.AutoService;
import com.squareup.javapoet.*;
import org.example.util.JavaTreeUtil;
import org.example.xtcs.annotate.ExtClass;

import javax.annotation.processing.*;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.TypeMirror;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Set;
import java.util.stream.Collectors;


/**
 * @ClassName: CreateExtClassAnnotaionProcessor2
 * @Description:
 * @Author: YourName
 * @Date: 2024/12/20
 */
//@SupportedAnnotationTypes("org.example.xtcs.annotate.ExtClass")
//@SupportedSourceVersion(SourceVersion.RELEASE_8)
//@AutoService(Processor.class)
public class CreateExtClassAnnotaionProcessor  extends AbstractProcessor {
    java.util.List<String> fieldNames = new ArrayList<>(Arrays.asList("xtcs1", "xtcs2", "xtcs3", "xtcs4", "xtcs5", "xtcs6", "xtcs7", "xtcs8", "xtcs9", "xtcs10"));
    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        for (Element element : roundEnv.getElementsAnnotatedWith(ExtClass.class)) {
            // 获取字段信息
            String className = element.getSimpleName().toString();
            TypeMirror fieldType = element.asType();
            System.out.println("类路径-------------" + fieldType.toString());
            //生成新的扩展类
            try {
                //反射获取类
                //获取该类所在包
                PackageElement packageElement = (PackageElement) processingEnv.getElementUtils().getPackageOf(element);
                //创建扩展类
                TypeSpec.Builder classBuilder = TypeSpec.classBuilder(className + "Ext")
                        .addModifiers(Modifier.PUBLIC);


                TypeSpec.Builder enumBuilder = TypeSpec.enumBuilder(className + "Enum");

                //添加字段
                fieldNames.stream().forEach(name -> {
                    System.out.println("生成字段【" + name + "】......");
                    //向枚举中添加枚举常量
                    enumBuilder.addEnumConstant(StrUtil.toUnderlineCase(name));

                    //向扩展类中添加字段
                    FieldSpec fieldSpec = FieldSpec.builder(String.class, name, Modifier.PRIVATE).build();
                    //set 方法
                    MethodSpec setName = MethodSpec.methodBuilder("set" + JavaTreeUtil.capitalize(name))
                            .addModifiers(Modifier.PUBLIC)
                            .returns(TypeName.VOID)
                            .addParameter(TypeName.get(String.class), name)
                            .addStatement("this.$N = $N", name, name) // 等价于 .addStatement("this.$1N = $1N", name)
                            .build();
                    //get 方法
                    MethodSpec getName = MethodSpec.methodBuilder("get" + JavaTreeUtil.capitalize(name))
                            .addModifiers(Modifier.PUBLIC)
                            .returns(TypeName.get(String.class))
                            .addStatement("return this.$N", name)
                            .build();

                    classBuilder.addMethod(getName);
                    classBuilder.addMethod(setName);
                    classBuilder.addField(fieldSpec);
                });

                //根据fieldNames 构建全参构造
                MethodSpec constructor = MethodSpec.constructorBuilder()
                        .addModifiers(Modifier.PUBLIC)
                        .addParameters(fieldNames.stream().map(name -> ParameterSpec.builder(String.class, name).build()).collect(Collectors.toList()))
                        .addCode(fieldNames.stream().map(name -> "this." + name + " = " + name + ";").collect(Collectors.joining("\n")))
                        .build();
                classBuilder.addMethod(constructor);
                // 生成Java文件
                System.out.println("package" + packageElement.toString());

                JavaFile javaFileEnum = JavaFile.builder(packageElement.toString(), enumBuilder.build()).build();


                JavaFile javaFile = JavaFile.builder(packageElement.toString(), classBuilder.build()).build();

                //生成普通扩展类
                javaFile.writeTo(processingEnv.getFiler());

                //生成枚举扩展类
                javaFileEnum.writeTo(processingEnv.getFiler());

            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return true;
    }
}
